package com.carnation.service.impl;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.apache.log4j.Logger;

import com.carnation.bean.FTPFileInfo;
import com.carnation.service.SFTPServer;
import com.carnation.utils.MenuFileUtril;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;

public class SFTPServerImpl implements SFTPServer{

	private Session sshSession =null;
	private ChannelSftp channelSftp = null;
	private MenuFileUtril menuFileUtril = new MenuFileUtril();
	private Logger logger = Logger.getLogger(SFTPServerImpl.class);
	
	private ChannelSftp getChannelSftp(){
		if(channelSftp != null && channelSftp.isConnected()){
			return channelSftp;
		}
		else{
			sshSession = getSession();
			try{
				Channel channel = sshSession.openChannel("sftp");
				channel.connect();
				channelSftp = (ChannelSftp)channel;
				return channelSftp;
			}
			catch(Exception e){
				logger.error("SFTP获取channel失败",e);
				return null;
			}
		}
	}
	
	private Session getSession(){
		if(sshSession == null || !sshSession.isConnected()){
			JSch jsch = new JSch();
			try {
				sshSession = jsch.getSession(menuFileUtril.getFTPUser(), menuFileUtril.getFTPHost(), menuFileUtril.getSSHPort());
				sshSession.setPassword(menuFileUtril.getFTPPasswd());
				sshSession.setConfig("StrictHostKeyChecking", "no");
				sshSession.connect();
				if(sshSession.isConnected()){
					logger.info("ssh成功链接");
				}
				else{
					logger.info("ssh链接失败");
				}
				return sshSession;
			} catch (JSchException e) {
				logger.error("链接SFTP出错",e);
				sshSession = null;
				return sshSession;
			}
		}
		else{
			return sshSession;
		}
	}
	
	
	@Override
	public void uploadFile(String path, String localName,String ftpName) {
		sshSession = getSession();
		try {
			Channel channel = sshSession.openChannel("sftp");
			channel.connect();
			ChannelSftp c = (ChannelSftp)channel;
			c.cd(path);
			OutputStream out = c.put(ftpName,ChannelSftp.OVERWRITE);
			InputStream is = new FileInputStream(localName);
			byte[] buff = new byte[1024*256];
			int read = -1;
			do{
				if(out != null){
					read = is.read(buff);
					if(read >0){
						out.write(buff, 0, read);
					}
				}
			}while(read >0);
			is.close();
			out.flush();
			out.close();
//			c.put(new FileInputStream(localName), path);
			c.disconnect();
		} catch (JSchException e) {
			logger.error("获取channel失败",e);
		} catch (SftpException e) {
			logger.error("切换路径错误",e);
		} catch (FileNotFoundException e) {
			logger.error("文件没有找到",e);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			logger.error("文件IO出错",e);
		}
	}

	@Override
	public void downloadFile(String path, String ftpName,String localfile) {
		sshSession = getSession();
		try {
			Channel channel = sshSession.openChannel("sftp");
			channel.connect();
			ChannelSftp c = (ChannelSftp)channel;
			c.cd(path);
			InputStream is = c.get(ftpName);
			OutputStream out = new FileOutputStream(localfile);
			int read = -1;
			byte[] buff = new byte[1024 * 256];
			do{
				if(is != null){
					read = is.read(buff);
					if(read > 0){
						out.write(buff, 0, read);
					}
					else{
						is.close();
					}
					out.flush();
				}
			}
			while(read > 0);
			out.close();
//			c.get(ftpName,new FileOutputStream(localfile));
			c.disconnect();
		} catch (JSchException e) {
			logger.error("获取channel失败",e);
		} catch (SftpException e) {
			logger.error("切换路径错误",e);
		} catch (FileNotFoundException e) {
			logger.error("文件没有找到",e);
		} catch (IOException e) {
			logger.error("文件IO出错",e);
		}
	}
	
	@Override
	public void close(){
		if(channelSftp != null){
			channelSftp.disconnect();
		}
		if(sshSession != null){
			sshSession.disconnect();
		}
	}
	
	@Override
	public boolean mkdir(String path,String directoryName){
		channelSftp = getChannelSftp();
		try {
			channelSftp.cd(path);
			channelSftp.mkdir(directoryName);
			return true;
		} catch (SftpException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}
	
	@Override
	public boolean rmdir(String path,String directoryName){
		try {
			channelSftp.cd(path);
			@SuppressWarnings("rawtypes")
			Vector v = channelSftp.ls(directoryName);
			if(v.size() > 2){
				logger.info("被删除的目录下有文件");
				return false;
			}
			else{
				channelSftp.rmdir(directoryName);
				return true;
			}
		} catch (SftpException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}
	
	@Override
	public List<FTPFileInfo> getFtpFileInfoByParent(String path){
		List<FTPFileInfo> ftpFileInfoList = new ArrayList<FTPFileInfo>();
		FTPFileInfo parentFile = new FTPFileInfo();
		parentFile.setFileName("..");
		ftpFileInfoList.add(parentFile);
		channelSftp = getChannelSftp();
		try {
			channelSftp.cd(path);
			@SuppressWarnings("rawtypes")
			Vector v = channelSftp.ls(".");
			for(int i =0;i<v.size();i++){
				LsEntry lsEntry = (LsEntry)v.get(i);
				if(!lsEntry.getFilename().startsWith(".")){
					SftpATTRS sftpATTRS = lsEntry.getAttrs();
					FTPFileInfo ftpFileInfo = new FTPFileInfo(lsEntry.getFilename(), Integer.toString(sftpATTRS.getUId()), Integer.toString(sftpATTRS.getGId()), 
							sftpATTRS.getSize(), getFileType(sftpATTRS), sftpATTRS.getAtimeString(), sftpATTRS.getPermissionsString());
					ftpFileInfoList.add(ftpFileInfo);
				}
			}
			return ftpFileInfoList;
		} catch (SftpException e) {
			e.printStackTrace();
			return ftpFileInfoList;
		}
	}
	
	private String getFileType(SftpATTRS sftpATTRS){
		if(sftpATTRS.isDir()){
			return "文件夹";
		}
		else if(sftpATTRS.isReg()){
			return "一般文件";
		}
		else if(sftpATTRS.isLink()){
			return "链接文件";
		}
		else{
			return "未知文件类型";
		}
	}
	
	@Override
	public Map<String,Long> findRegularFileList(String path){
		Map<String,Long> map = new HashMap<String,Long>();
		channelSftp = getChannelSftp();
		try {
			channelSftp.cd(path);
			@SuppressWarnings("rawtypes")
			Vector v = channelSftp.ls(".");
			for(int i =0 ; i<v.size();i++){
				LsEntry lsEntry = (LsEntry)v.get(i);
				if(lsEntry.getAttrs().isReg()){
					map.put(lsEntry.getFilename(),lsEntry.getAttrs().getSize());
				}
			}
			return map;
		} catch (SftpException e) {
			logger.error("路径不存在",e);
			return new HashMap<String,Long>();
		}
	}

	@Override
	public String getPath(String path) throws SftpException{
		channelSftp = getChannelSftp();
		try {
			channelSftp.cd(menuFileUtril.getFTPStorePath());
		} catch (SftpException e) {
			e.printStackTrace();
		}
		String[] p = path.split("/");
		for(int i =0;i<p.length;i++){
			channelSftp.cd(p[i]);
		}
		return channelSftp.pwd();
	}

	@Override
	public InputStream findFileStreamByRealPathAndFileName(String realpath,
			String filename) {
		channelSftp = getChannelSftp();
		try {
			channelSftp.cd(realpath);
			return channelSftp.get(filename);
		} catch (SftpException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}

	@Override
	public String deleteFile(String path, String fileName) {
		channelSftp = getChannelSftp();
		try {
			channelSftp.cd(path);
			@SuppressWarnings("rawtypes")
			Vector v= channelSftp.ls(".");
			LsEntry target = null;
			for(int i=0;i<v.size();i++){
				LsEntry lsEntry = (LsEntry)v.get(i);
				if(lsEntry.getFilename().equals(fileName)){
					target = lsEntry;
					break;
				}
			}
			if(target == null){
				return "404";
			}
			else{
				if(target.getAttrs().isDir()){
					channelSftp.cd(target.getFilename());
					if(channelSftp.ls(".").size() == 0){
						channelSftp.cd("..");
						channelSftp.rmdir(target.getFilename());
						return "200";
					}
					else{
						return "304";
					}
				}
				else if(target.getAttrs().isReg()){
					channelSftp.rm(target.getFilename());
					return "200";
				}
				else{
					return "500";
				}
			}
		} catch (SftpException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return "500";
		}
	}
}
